{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 重新读入数据，使用GBDT+LR"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import scipy as sc\n",
    "import scipy.sparse as sp\n",
    "from sklearn.utils import check_random_state \n",
    "import pylab \n",
    "import sys\n",
    "import time\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "fea0_1=pd.read_csv('~/10w_train_count_day_hash.csv')\n",
    "fea1_1=pd.read_csv('~/test_count_day_hash.csv')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_train = fea0_1['click']\n",
    "train = fea0_1.drop([ \"click\",\"id\",\"hour\",\"user_count\",\"hour_int\"], axis=1)\n",
    "X_test = fea1_1.drop([\"id\",\"hour\",\"user_count\",\"hour_int\"], axis=1)\n",
    "X_train = train"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Index(['C1', 'banner_pos', 'site_id', 'site_domain', 'site_category', 'app_id',\n",
       "       'app_domain', 'app_category', 'device_id', 'device_ip', 'device_model',\n",
       "       'device_type', 'device_conn_type', 'C14', 'C15', 'C16', 'C17', 'C18',\n",
       "       'C19', 'C20', 'C21', 'device_id_count', 'device_ip_count', 'day_week',\n",
       "       'hour_day', 'is_weekend'],\n",
       "      dtype='object')"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train.columns"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "catNum=['site_id','site_domain','site_category','app_id','app_domain',\n",
    "        'app_category','device_id','device_ip','device_model','C17','C19',\n",
    "        'C20','C21','hour_day','device_id_count','device_ip_count','user_count']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "features_one=['C1','banner_pos','device_type','device_conn_type','C15','C16','C18','day_week','is_weekend']\n",
    "X_train_one=X_train[features_one]\n",
    "X_test_one=X_test[features_one]\n",
    "X_train_two=X_train.drop(features_one,axis=1)\n",
    "X_test_two=X_test.drop(features_one,axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "(train_rows_1, cols_1) = X_train_one.shape\n",
    "X_data_one = pd.concat([X_train_one, X_test_one], axis = 0, ignore_index=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import OneHotEncoder\n",
    "oneHot=OneHotEncoder()\n",
    "X_data_one_hot=oneHot.fit_transform(X_data_one)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_data_one_hot=X_data_one"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn.model_selection import StratifiedKFold\n",
    "from sklearn.metrics import log_loss\n",
    "from xgboost import XGBClassifier\n",
    "import xgboost as xgb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "XGBClassifier(base_score=0.16, booster='gbtree', colsample_bylevel=0.9,\n",
       "       colsample_bytree=0.5, gamma=0, learning_rate=0.4, max_delta_step=0,\n",
       "       max_depth=8, min_child_weight=50, missing=None, n_estimators=35,\n",
       "       n_jobs=1, nthread=None, objective='binary:logistic', random_state=0,\n",
       "       reg_alpha=2.5, reg_lambda=0.5, scale_pos_weight=1, seed=999,\n",
       "       silent=True, subsample=1.0)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#先寻找最佳的树个数，n_estimators=157\n",
    "#params = {\"objective\": \"multi:softprob\", \"eval_metric\":\"mlogloss\", \"num_class\": 9}\n",
    "xgb1 = XGBClassifier(\n",
    "        learning_rate =0.4,\n",
    "        n_estimators=35,   #数值大没关系，使用交叉验证，cv会自动返回合适的n_estimators  \n",
    "        max_depth=8,\n",
    "        min_child_weight=50, # 叶子节点所需要的最小样本权重和,大小容易过拟合\n",
    "        gamma=0,\n",
    "        subsample = 1.0,#0.85\n",
    "        colsample_bytree=0.5,\n",
    "        colsample_bylevel=0.9,\n",
    "        reg_alpha = 2.5,\n",
    "        reg_lambda= 0.5,\n",
    "        base_score=0.16,\n",
    "        objective= 'binary:logistic',\n",
    "        seed=999)\n",
    "#'base_score':0.16, 'seed': 999  'verbose':0,\n",
    "# 训练数据：X_train_part, y_train_part   验证数据：X_val, y_val\n",
    "xgb1.fit(X_train_two, y_train, eval_metric='logloss')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f10168c60f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "####xgboost进行特征重要性的选择\n",
    "#可以使用XGBoost内嵌的函数，按特征重要性排序\n",
    "from xgboost import plot_importance\n",
    "plot_importance(xgb1)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "X_train_three, X_test_three, y_train_one, y_test_one = train_test_split(X_train,y_train,test_size=0.2,random_state=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.001, n=26, Accuracy: 83.10%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.002, n=25, Accuracy: 83.10%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.004, n=24, Accuracy: 83.01%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.005, n=23, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.005, n=23, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.005, n=23, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.007, n=20, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.013, n=19, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.019, n=18, Accuracy: 82.97%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.022, n=17, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.022, n=17, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.026, n=15, Accuracy: 82.97%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.027, n=14, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.028, n=13, Accuracy: 82.97%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.034, n=12, Accuracy: 82.97%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.042, n=11, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.043, n=10, Accuracy: 82.97%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.049, n=9, Accuracy: 83.00%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.051, n=8, Accuracy: 83.01%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.052, n=7, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.069, n=6, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.073, n=5, Accuracy: 83.04%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.083, n=4, Accuracy: 82.99%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.087, n=3, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Thresh=0.102, n=2, Accuracy: 82.98%\n",
      "Thresh=0.130, n=1, Accuracy: 82.98%\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/fuxi/anaconda3/lib/python3.6/site-packages/sklearn/preprocessing/label.py:151: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.\n",
      "  if diff:\n"
     ]
    }
   ],
   "source": [
    "#可以根据特征重要性进行特征选择\n",
    "from numpy import sort\n",
    "from sklearn.feature_selection import SelectFromModel\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.metrics import roc_auc_score\n",
    "# Fit model using each importance as a threshold\n",
    "thresholds = sort(xgb1.feature_importances_)\n",
    "for thresh in thresholds:\n",
    "  # select features using threshold\n",
    "  selection = SelectFromModel(xgb1, threshold=thresh, prefit=True)\n",
    "  select_X_train = selection.transform(X_train_three)\n",
    "  # train model\n",
    "  selection_model = XGBClassifier()\n",
    "  selection_model.fit(select_X_train, y_train_one)\n",
    "# eval model\n",
    "  select_X_test = selection.transform(X_test_three)\n",
    "  y_pred = selection_model.predict(select_X_test)\n",
    "  predictions = [round(value) for value in y_pred]\n",
    "  accuracy = accuracy_score(y_test_one, predictions)\n",
    "  print(\"Thresh=%.3f, n=%d, Accuracy: %.2f%%\" % (thresh, select_X_train.shape[1],\n",
    "      accuracy*100.0))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "xgb_train=xgb1.apply(X_train_two)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 90  88  69  98  94 101  31  65  80  88 205 150  62  62  88 124  38  56\n",
      "  61  89  42  80  27 136  34  67  27  91  56  39  47  52  64  81  67]\n"
     ]
    }
   ],
   "source": [
    "print(xgb_train[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "xgb_test =xgb1.apply(X_test_two) #学习率，太低导致不能快速收敛，肯出现memory error？？\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "(train_rows_2, cols_2) = xgb_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "xgb_data=np.concatenate((xgb_train,xgb_test),axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "#调用one-hot编码,对叶子结点进行编码\n",
    "#使用训练好的GBDT模型构建特征，然后将特征经过one-hot编码作为新的特征输入到LR模型训练。\n",
    "from sklearn.preprocessing import OneHotEncoder\n",
    "oneHot = OneHotEncoder()\n",
    "#使用xgb_data训练GBDT模型，后面用此模型构造特征\n",
    "lr_data=oneHot.fit_transform(xgb_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "lr_data=xgb_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_one_1=X_data_one_hot[:train_rows_1,:]\n",
    "test_one_1=X_data_one_hot[train_rows_1:,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_one_2=lr_data[:train_rows_2,:]\n",
    "test_one_2=lr_data[train_rows_2:,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.sparse import hstack\n",
    "lr_train = hstack((train_one_1,train_one_2)) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "labelencoder=LabelEncoder()\n",
    "for col in X_train_one.columns:\n",
    "    X_train_one[col] = labelencoder.fit_transform(X_train_one[col])\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "from scipy.sparse import hstack\n",
    "lr_train=hstack((X_train_one,lr_data))\n",
    "lr_test =hstack((test_one_1,test_one_2))\n",
    "lr_test =test_one_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.4363249939100745\n",
      "{'C': 0.01, 'penalty': 'l1'}\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn.linear_model import LogisticRegression\n",
    "from sklearn.linear_model import LogisticRegressionCV\n",
    "#需要调优的参数\n",
    "# 请尝试将L1正则和L2正则分开，并配合合适的优化求解算法（slover）\n",
    "tuned_parameters = {'penalty':['l1','l2'],\n",
    "                   'C': [0.014, 0.012, 0.01,0.08,0.06]\n",
    "                   }\n",
    "lr=LogisticRegression();\n",
    "#penaltys = ['l1','l2']\n",
    "#s = [0.01, 0.1, 1,10,100] #使用cv时必须要有list变化的参数\n",
    "#uned_parameters = dict(penalty = penaltys, C = Cs)\n",
    "grid= GridSearchCV(lr, tuned_parameters,cv=5, scoring='neg_log_loss')\n",
    "grid.fit(lr_train,y_train)\n",
    "print(-grid.best_score_)\n",
    "print(grid.best_params_)\n",
    "#lr=LogisticRegression(C=11, penalty='l2',solver='liblinear')\n",
    "#lr.fit(lr_train,y_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.4215660656902865\n"
     ]
    }
   ],
   "source": [
    "train_predprob = grid.predict_proba(lr_train)\n",
    "logloss = log_loss(y_train, train_predprob)\n",
    "print(logloss)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pickle\n",
    "pickle.dump(grid,open(\"lr_model.pkl\",'wb'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "y_test_pred=grid.predict_proba(lr_test)[:,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [],
   "source": [
    "submission=pd.read_csv('/home/fuxi/sampleSubmission')\n",
    "sample_id=submission['id']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "sub_one=pd.DataFrame(y_test_pred)\n",
    "sub_one.columns=['click']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [],
   "source": [
    "sub_file=pd.concat([sample_id,sub_one],axis=1)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
